package com.ruoyi.web.controller.word;

import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.ErrorCode;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.domain.word.CommonWord;
import com.ruoyi.common.domain.word.CommonWordPronounce;
import com.ruoyi.common.domain.word.CommonWordRa;
import com.ruoyi.common.domain.word.CommonWordSentence;
import com.ruoyi.word.service.ICommonWordFormService;
import com.ruoyi.word.service.ICommonWordPronounceService;
import com.ruoyi.word.service.ICommonWordService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/word")
public class CommonWordController extends BaseController {

    @Autowired
    private ICommonWordService biz;

    @Autowired
    private ICommonWordPronounceService commonWordPronounceService;


    @Autowired
    private ICommonWordFormService formService;

    @Autowired
    private RestTemplate restTemplate;

//    @Value("${apiHost}")
//    private String apiHost;

    @RequestMapping(value = "/find", method = RequestMethod.GET)
    public R find(String sort, String order, String page, String size, String keyword, String word, String prefix,
                  String stem, String suffix, Long sid, Integer realSubWordFreqGt, Integer realSubWordFreqLt) {
        try{
            if(StringUtils.isEmpty(sort)) {
                sort = "add_time"; order = "desc";
            }
           startPage();
            return R.data(new PageInfo<>(biz.findByWhereStr(buildParam(keyword, word, prefix, stem, suffix, sid, realSubWordFreqGt, realSubWordFreqLt), sort, order)));
        }catch(Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }

    private String buildParam(String keyword, String word, String prefix, String stem, String suffix,
                              Long sid, Integer realSubWordFreqGt, Integer realSubWordFreqLt){
        StringBuilder whereStr = new StringBuilder("1 = 1 ");
        if(StringUtils.isNotEmpty(keyword)) {
            whereStr.append(" and name like '%" + keyword + "%'");
        }
        if(StringUtils.isNotEmpty(word)) {
            whereStr.append(" and name = '" + word + "'");
        }
        if(StringUtils.isNotEmpty(prefix)) {
            whereStr.append(" and exists (select 1 from " + CommonWordRa.TABLE_NAME + " tp where tp.name='" + prefix + "' and type=" + CommonWordRa.TYPE_PREFIX + " and tp.wid=p.id)");
        }
        if(StringUtils.isNotEmpty(stem)) {
            whereStr.append(" and exists (select 1 from " + CommonWordRa.TABLE_NAME + " tp where tp.name='" + stem + "' and type=" + CommonWordRa.TYPE_STEM + " and tp.wid=p.id)");
        }
        if(StringUtils.isNotEmpty(suffix)) {
            whereStr.append(" and exists (select 1 from " + CommonWordRa.TABLE_NAME + " tp where tp.name='" + suffix + "' and type=" + CommonWordRa.TYPE_SUFFIX + " and tp.wid=p.id)");
        }
        if(sid != null) {
            whereStr.append(" and exists (select 1 from " + CommonWordSentence.TABLE_NAME  + " cs where cs.sid = " + sid + " and cs.wid = p.id) ");
        }
        if(realSubWordFreqGt != null) {
            whereStr.append(" and real_sub_word_freq >= '" + realSubWordFreqGt + "'");
        }
        if(realSubWordFreqLt != null) {
            whereStr.append(" and real_sub_word_freq < '" + realSubWordFreqLt + "'");
        }
        buildTimeQuerySql(whereStr, "update_time");
        return whereStr.toString();
    }

    @PostMapping("/save")
    public R save(@RequestBody CommonWord record){
        try {
            if(StringUtils.isEmpty(record.getName())) {
                return R.fail(ErrorCode.INVALID_PARAMETERS);
            }
            if(biz.findByWord(record.getName()) != null) {
                return R.fail(ErrorCode.ALREADY_EXISTS);
            }
            return R.data(biz.save(record));
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }

    @PutMapping("/update")
    public R update(@RequestBody CommonWord record){
        try {
            if(record.getId() == null || StringUtils.isEmpty(record.getName())) {
                return R.fail(ErrorCode.INVALID_PARAMETERS);
            }
            return R.data(biz.update(record));
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }

    @DeleteMapping("/del/{id}")
    public R delete(@PathVariable Long id){
        try {
            return R.data(biz.delete(id));
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }

    @GetMapping("/findById/{id}")
    public R findById(@PathVariable Long id){
        try {
            return R.data(biz.findById(id));
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }

    @GetMapping("/findByWord")
    public R findByWord(@RequestParam String word){
        try {
            return R.data(biz.findByWord(word));
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }

    @PostMapping("/uploadBatch")
    public R uploadBatch(@RequestBody List<CommonWord> records) {
        try{
            if(records == null || records.isEmpty()) {
                return R.fail("empty_data");
            }
            Map<Long, String> errMsg = new HashMap<>();
            //循环处理数据
            records.stream().forEach(record ->{
                try{
                    if(StringUtils.isEmpty(record.getName())){
                        errMsg.put(record.getId(), "invalid_parameters");
                        return;
                    }
                    System.out.println(JSON.toJSONString(record));
                    record.setName(record.getName().trim());
                    CommonWord _r = biz.findByWord(record.getName());
                    if(_r != null){
                        //errMsg.put(record.getId(), "phone_exists");
                        //return;
                        record.setId(_r.getId());
                        biz.update(record);
                    }else {
                        record.setId(null);
                        biz.save(record);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            });
            return R.data(errMsg);
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }

//    @PostMapping("/updateAllExSenPreNum")
//    public R updateAllExSenPreNum() {
//        try {
//            List<CommonWord> list = biz.findByWhereStr("", null, null);
//            list.stream().forEach(w -> {
//                CommonWord word = new CommonWord();
//                word.setId(w.getId());
//                word.setExSenPreNum(subjectSentenceService.findByWord(w.getName(), 0, 99999, null).size());
//                biz.updateByPrimaryKeySelective(word);
//            });
//        }catch (Exception e){
//            logger.error("updateAllExSenPreNum", e);
//        }
//        return R.error();
//    }

//    @PostMapping("/updateRealSubWordFreq")
//    // @Scheduled(fixedDelay = 1000*60*60*24*10)
//    public R updateRealSubWordFreq() {
//        while (true) {
//            int pn = 1;
//            PageHelper.startPage(pn, 1000, false);
//            List<CommonWord> list = biz.findByWhereStr("", null, null);
//            if(CollectionUtils.isEmpty(list)) {
//                break;
//            }
//            list.stream().forEach(w -> {
//                Set<String> words = new HashSet<>();
//                words.add(w.getName());
//                // 获取单词的其他形式
//                List<CommonWordForm> forms = formService.findByWid(w.getId());
//                forms.forEach(d -> {
//                    String value = d.getValue();
//                    if(StringUtils.isEmpty(value)){
//                        return;
//                    }
//                    if(!StringUtils.contains(value, "或")) {
//                        words.add(value.trim());
//                    } else {
//                        String[] ns = value.split("或");
//                        for (String n: ns) {
//                            if(StringUtils.isNotEmpty(n)){
//                                words.add(n.trim());
//                            }
//                        }
//                    }
//                });
//                CommonWord word = new CommonWord(w.getId());
//                word.setRealSubWordFreq(subjectSentenceService.findRealSubWordFreq(words));
//                biz.updateByPrimaryKeySelective(word);
//            });
//        }
//        return R.error();
//    }

//    @GetMapping("/download")
//    public void download(HttpServletResponse response, String sort, String order, String keyword, String word, String prefix,
//                         String stem, String suffix, Long sid, Integer realSubWordFreqGt, Integer realSubWordFreqLt) throws IOException {
//        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
//        try {
//            response.setContentType("application/vnd.ms-excel");
//            response.setCharacterEncoding("utf-8");
//            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
//            String fileName = URLEncoder.encode("单词列表", "UTF-8");
//            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//            // 这里需要设置不关闭流
//            if(StringUtils.isEmpty(sort)) {
//                sort = "p.add_time";
//            }else{
//                sort = "p." + sort;
//            }
//            List<CommonWord> data = biz.findByWhereStr(buildParam(keyword, word, prefix, stem, suffix, sid, realSubWordFreqGt, realSubWordFreqLt), sort, "desc");
//            EasyExcel.write(response.getOutputStream(), CommonWordExcelVO.class).autoCloseStream(Boolean.FALSE).sheet("单词")
//                    .doWrite(toExcelVo(data));
//        } catch (Exception e) {
//            // 重置response
//            response.reset();
//            response.setContentType("application/json");
//            response.setCharacterEncoding("utf-8");
//            response.getWriter().println(JSON.toJSONString(R.error()));
//        }
//    }
//
//    private List<CommonWordExcelVO> toExcelVo(List<CommonWord> data){
//        List<CommonWordExcelVO> result = new ArrayList<>(data.size());
//        data.stream().forEach(d -> {
//            CommonWordExcelVO vo = new CommonWordExcelVO();
//            BeanUtils.copyProperties(d, vo);
//            result.add(vo);
//        });
//        return result;
//    }

    /**
     * 百度音标单词拉取
     * @param id
     * @return
     */
    @GetMapping("/pull/baidu/{id}")
    public R baiduPull(@PathVariable("id")Long id){
        try {
            CommonWord word = biz.findById(id);
            if(word == null){
                return R.fail("未查到单词");
            }

            List<CommonWordPronounce> datas = commonWordPronounceService.findById(id);
            //如果没有查到音标
            if(CollectionUtils.isEmpty(datas)){
                Map<String, Object> result = commonWordPronounceService.doBaiduPull(word);
                return R.data(result);
            }

            //是否有音标或者读音未补充的
            boolean flag = false;
            for (CommonWordPronounce data : datas) {
                if(StringUtils.isEmpty(data.getAudio()) || StringUtils.isEmpty(data.getContent())){
                    flag = true;
                }
            }
            if(flag){
                Map<String, Object> result = commonWordPronounceService.doBaiduPull(word);
                return R.data(result);
            }
            Map<String, Object> result = new HashMap<>();
            result.put("flag", true);
            result.put("msg", "数据已存在，不用拉取");
            return R.data(result);
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }

    /**
     * 有道音标单词拉取
     * @param id
     * @return
     */
    @GetMapping("/pull/youdao/{id}")
    public R youdaoPull(@PathVariable("id")Long id){
        try {
            CommonWord word = biz.findById(id);
            if(word == null){
                return R.fail("未查到单词");
            }

            List<CommonWordPronounce> datas = commonWordPronounceService.findById(id);
            //如果没有查到音标
            if(CollectionUtils.isEmpty(datas)){
                Map<String, Object> result = commonWordPronounceService.doYoudaoPull(word);
                return R.data(result);
            }

            //是否有音标或者读音未补充的
            boolean flag = false;
            for (CommonWordPronounce data : datas) {
                if(StringUtils.isEmpty(data.getAudio()) || StringUtils.isEmpty(data.getContent())){
                    flag = true;
                }
            }
            if(flag){
                Map<String, Object> result = commonWordPronounceService.doYoudaoPull(word);
                return R.data(result);
            }
            Map<String, Object> result = new HashMap<>();
            result.put("flag", true);
            result.put("msg", "数据已存在，不用拉取");
            return R.data(result);
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }


    /**
     * 百度音标单词拉取
     * @param ids
     * @return
     */
    @GetMapping("/pull/baidu/batch")
    public R baiduBatchPull(@RequestParam(value = "ids", required = false)List<Long> ids){
        try {
            if(CollectionUtils.isEmpty(ids)){
                return R.fail("请求参数为空");
            }
            Map<String,Object> result = new HashMap<>();
            int successNum = 0;
            int failNum = 0;
            for (Long id : ids) {
                CommonWord word = biz.findById(id);
                if(word == null){
                    failNum++;
                    continue;
                }
                List<CommonWordPronounce> datas = commonWordPronounceService.findById(id);
                //如果没有查到音标
                if(CollectionUtils.isEmpty(datas)){
                    Map<String, Object> baiduResult = commonWordPronounceService.doBaiduPull(word);
                    boolean flag = (boolean) baiduResult.get("flag");
                    if(flag){
                        successNum++;
                    }else{
                        failNum++;
                    }
                    continue;
                }

                //是否有音标或者读音未补充的
                boolean flag = false;
                for (CommonWordPronounce data : datas) {
                    if(StringUtils.isEmpty(data.getAudio()) || StringUtils.isEmpty(data.getContent())){
                        flag = true;
                    }
                }
                if(flag){
                    Map<String, Object> baiduResult = commonWordPronounceService.doBaiduPull(word);
                    boolean resultFlag = (boolean) baiduResult.get("flag");
                    if(resultFlag){
                        successNum++;
                    }else{
                        failNum++;
                    }
                    continue;
                }
                successNum++;
            }
            result.put("successNum",successNum);
            result.put("failNum",failNum);
            return R.data(result);
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.fail();
    }

//    @GetMapping("/precise")
//    public R precise(@RequestParam String word) {
//        ResponseEntity<R> re = restTemplate.exchange(apiHost + "/api/word/precise?word=" + word,
//                HttpMethod.GET, HttpEntity.EMPTY, R.class);
//        if(re.getBody() == null || re.getBody().getCode() != 200) {
//            return re.getBody();
//        }
//        return re.getBody();
//    }
}
